home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
surfmodl
/
surfm203.arc
/
SURFSRC.ARC
/
SURFGRAF.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1988-01-31
|
22KB
|
779 lines
{$I defines.inc}
Unit SURFGRAF;
{Graphics primitives for Surfmodl. These primitives use the borland .BGI }
{routines. If you add support for a new graphics system, you must update }
{the SYS_NAME, LGLSYS, MAXSYS, and perhaps OLDSYS routines. You also must}
{update the SURFBGI bgi emulation routines}
INTERFACE
uses crt,
{$IFDEF EXTERNAL}
SURFbgi;
{$ELSE}
Graph;
{$ENDIF}
{$IFDEF USE8087}
type real = single;
{$ENDIF}
{ Names of all the systems currently supported by SURFMODL: }
const MAXSYS = 11; { maximum # of systems currently supported }
const Sys_name: array[1..MAXSYS] of string[30] = (
'IBM Color Graphics Adapter',
'IBM MCGA Graphics Adapter',
'IBM Enhanced Graphics Adapter',
'IBM EGA with 64K memory',
'IBM EGA with Mono Display',
'RESERVED',
'Hercules Nono Graphics Adapter',
'AT&T 6300 400 line mode',
'IBM VGA Graphics Adapter',
'IBM 3270',
{$IFDEF VAXMATE }
'DEC Vaxmate'
{$ELSE}
'RESERVED' {<<<<<< Note, this must be present and in CAPS to work}
{$ENDIF}
);
LGLSYS: array[1..MAXSYS] of integer = (
CGA,
MCGA,
EGA,
EGA64,
EGAMONO,
RESERVED,
HERCMONO,
ATT400,
VGA,
PC3270,
{$IFDEF VAXMATE} {Make unused systems RESERVED}
VM400
{$ELSE}
RESERVED
{$ENDIF}
);
{table to convert old Surfmodl 1.x system number to new}
const oldsys :array[1..10] of integer = (
CGA, { CGA : old number 1}
EGA, { EGA : old number 2}
HERCMono, { HERCMono : old number 3}
detect, { Sanyo Unsupported, try to detect}
detect, { Heath/Zenith Z-100 Unsupported, try to detect }
CGA, { Toolbox CGA, old number 6 }
ATT400, { AT&T 6300 mode, old number 7 }
PC3270, { IBM 3270, old number 8 }
EGA64, { Old QUADEGA (640x480), closest is (640x350) }
EGA64); { Old QUADEGA (752x410), closest is (640x350) }
var
driveron : boolean; { flag for if driver is on or not }
grsys : integer; { Graphics system being used }
grmode : integer; { Graphics mode in the system }
dorandom : boolean; { flag for random interpolation }
RandShade : real; { Random shade pattern }
Ngraphchar: integer; { #chars across graphics screen}
{ If 0 then no text will be
displayed on the graphics screen }
Gxmin, Gxmax,
Gymin, Gymax: integer; { graphics screen limits }
ncolors : integer; { Number of colours supported in current mode}
MONO : boolean; { Flag for monochrome graphics }
Viewchanged : boolean; { Flag for changed viewpoint }
Flpurpose: string[127]; { title for plot }
BGIDIR : string;
procedure gplot (x,y,color:integer);
procedure exgraphic;
procedure closedriver; {shuts down entire graphics system }
procedure GDRAW (X1t, Y1t, X2t, Y2t, Color: integer);
procedure GHDRAW (X1, X2, Y, Color: integer);
procedure SHPLOT (X, Y, Color: integer; Fmod: integer);
procedure SHDRAW (X1, X2, Y, Color: integer; Fmod: integer);
procedure setsys;
procedure SETGMODE;
procedure stopstat;
function grafstat : boolean;
function checkey : boolean;
function savescrn (filename : string) : boolean;
function readscrn (filename : string; var grsys,grmode : integer;
var bitmap : pointer) : boolean;
IMPLEMENTATION
procedure gplot (x,y,color:integer);
{plot one dot in given colour, with clipping}
begin
putpixel (x,y,color);
end;
procedure EXGRAPHIC;
{ Exit graphics mode }
begin
RestoreCrtMode;
end; { procedure EXGRAPHIC }
procedure closedriver;
{ closes down the existing graphics system }
begin
if driveron then begin
setgraphmode(grmode);
closegraph;
driveron := false;
end;
end;
{ NOTE: This file contains several routines, which are the system-independent
graphics primitives of SURFMODL:
GDRAW - Line drawing routine
GHDRAW - Horizontal line drawing routine
SHPLOT - Shaded pixel plot routine
SHDRAW - Shaded line drawing routine
DITHPLOT - Dithered pixel plot routine
DITHDRAW - Dithered line drawing routine
INTRPLOT - Interpolated pixel plot routine
INTRDRAW - Interpolated line drawing routine
}
{ System Independent Line draw }
procedure GDRAW (X1t, Y1t, X2t, Y2t, Color: integer);
{ This routine was written by Russell Nelson, to draw a line using the
GPLOT primitive -- for systems that do not provide a line drawing
primitive. This routine does NOT clip. }
var
delta_x, delta_y : integer;
inc_x, inc_y : integer;
epsilon, count : integer;
x1, y1, x2, y2: integer;
begin
if (x2t < x1t) then begin
{ Make sure the lines are always plotted in the same direction, for
smooth line drawing in hidden line removal. }
x1 := x2t;
y1 := y2t;
x2 := x1t;
y2 := y1t;
end else begin
x1 := x1t;
y1 := y1t;
x2 := x2t;
y2 := y2t;
end;
delta_x := abs(x2 - x1);
delta_y := abs(y2 - y1);
{ if x2 > x1 then inc_x := 1 else inc_x := -1; }
inc_x := 1;
if y2 > y1 then inc_y := 1 else inc_y := -1;
if delta_x > delta_y then begin
count := delta_x + 1;
epsilon := delta_x div 2;
while count>0 do begin
GPLOT(x1, y1, Color);
epsilon := epsilon + delta_y;
if epsilon > delta_x then begin
epsilon := epsilon - delta_x;
y1 := y1 + inc_y;
end;
x1 := x1 + inc_x;
count := count - 1;
end;
end else begin
count := delta_y + 1;
epsilon := delta_y div 2;
while count>0 do begin
GPLOT(x1, y1, Color);
epsilon := epsilon + delta_x;
if epsilon > delta_y then begin
epsilon := epsilon - delta_y;
x1 := x1 + inc_x;
end;
y1 := y1 + inc_y;
count := count - 1;
end;
end;
end; { procedure GDRAW }
{ GHDRAW: Horizontal line draw.}
procedure GHDRAW (X1, X2, Y, Color: integer);
{ Special fast version that does its own clipping}
var X: integer;
X1t, X2t: integer;
begin
gdraw (x1,y,x2,y,color);
end; { procedure GHDRAW }
procedure SHPLOT (X, Y, Color: integer; Fmod: integer);
{ system-independent shaded pixel plot command }
{ This routine uses the system's colors as shades of grey }
begin
if (Fmod > 1) then begin
if (X mod Fmod = Y mod Fmod) then
gplot (X, Y, Color)
else
gplot (X, Y, 0);
end else if (Fmod < -1) then begin
if (X mod -Fmod = Y mod -Fmod) then
gplot (X, Y, 0)
else
gplot (X, Y, Color);
end else
gplot (X, Y, Color);
end; { procedure SHPLOT }
procedure SHDRAW (X1, X2, Y, Color: integer; Fmod: integer);
{ system-independent shaded horizontal line drawing command }
{ This routine uses the system's colors as shades of grey }
var X: integer; { x coord }
begin
if (abs(Fmod) < 2) then
ghdraw (X1, X2, Y, Color)
else if (Fmod > 1) then begin
for X := X1 to X2 do
if (X mod Fmod = Y mod Fmod) then
gplot (X, Y, Color)
else
gplot (X, Y, 0);
end else begin
for X := X1 to X2 do
if (X mod -Fmod = Y mod -Fmod) then
gplot (X, Y, 0)
else
gplot (X, Y, Color);
end;
end; { procedure SHDRAW }
procedure SETSYS;
{ Initialize system-dependent parameters, and check for hardware presence
if possible. (Ncolors is set to 0 if the hardware is known to not be
present.
}
var
sys : integer;
message : string;
modelow,modehi : integer;
num : integer;
code : integer;
begin
if not driveron then begin
initgraph (grsys,grmode,BGIDIR);
if graphresult < 0 then begin
grsys := detect;
initgraph (grsys,grmode,BGIDIR);
if graphresult < 0 then begin
writeln (grapherrormsg(grsys));
writeln;
writeln ('If the .BGI files are not in the current directory');
writeln ('then you can use SET to set an environment variable');
writeln ('called BGIDIR which points to the .BGI file directory.');
writeln;
writeln ('SurfModl Halted');
halt(1);
end; {Error initializing hardware from detect}
end; { error initializing selected hardware, try detect }
restorecrtmode;
driveron := true;
end {Driver not successfully initialized yet }
else
driveron := false;
Message := 'No error';
{Write the menu options}
While not driveron do begin
clrscr;
if Message = 'No error' then
writeln
else
writeln ('GRAPH ERROR: ',message,^G);
writeln;
writeln ('Choose from the following system types:');
for Sys := 1 to MAXSYS do
if (Sys_name[lglsys[sys]] <> 'RESERVED') then
writeln (Lglsys[Sys]:3,' ',Sys_name[Lglsys[Sys]]);
grsys := 1;
repeat
write ('System Number (',grsys,'): ');
readln (message);
if message = '' then
str (grsys,message);
val(message,num,code);
until ((code = 0) and (trunc(num) in [1..MAXSYS]) and
(SYS_NAME[lglsys[num]] <> 'RESERVED'));
grsys := trunc(num);
{Get mode for this driver}
clrscr;
getmoderange(grsys,modelow,modehi);
if modelow <> modehi then begin {Select the graphics mode}
writeln ('Choose from the following graphics modes:');
Case grsys of
CGA : begin
writeln (' 0: 320x200, Lightgreen Lightred, Yellow');
writeln (' 1: 320x200, LightCyan, LightMagenta, White');
writeln (' 2: 320x200, Green, Red, Brown');
writeln (' 3: 320x200, Cyan, Magenta, Lightgrey');
writeln (' 4: 640x200, one colour');
end;
MCGA: Begin
writeln (' 0: 320x200, Lightgreen Lightred, Yellow');
writeln (' 1: 320x200, LightCyan, LightMagenta, White');
writeln (' 2: 320x200, Green, Red, Brown');
writeln (' 3: 320x200, Cyan, Magenta, Lightgrey');
writeln (' 4: 640x200, one colour');
writeln (' 5: 640x480, one colour');
end;
EGA : Begin
writeln (' 0: 640x200, 16 Colour');
writeln (' 1: 640x350, 16 Colour');
end;
EGA64: Begin
writeln (' 0: 640x200, 16 Colour');
writeln (' 1: 640x350, 4 Colour');
end;
EGAMONO: Begin
writeln (' 3: 640x350, 1 Colour');
end;
HercMONO: Begin
writeln (' 0: 720x348, 1 Colour');
end;
ATT400: Begin
writeln (' 0: 320x200, Lightgreen Lightred, Yellow');
writeln (' 1: 320x200, LightCyan, LightMagenta, White');
writeln (' 2: 320x200, Green, Red, Brown');
writeln (' 3: 320x200, Cyan, Magenta, Lightgrey');
writeln (' 4: 640x200, one colour');
writeln (' 5: 640x400, one colour');
end;
VGA: Begin
writeln (' 0: 640x200, 16 Colour');
writeln (' 1: 640x350, 16 Colour');
writeln (' 2: 640x480, 16 Colour');
end;
PC3270: Begin
writeln (' 0: 720x350, 1 Colour');
end;
{$IFDEF VAXMATE} {DEC VAXMATE modes}
VM400 : begin
writeln (' 0: 320x200, Lightgreen Lightred, Yellow');
writeln (' 1: 320x200, LightCyan, LightMagenta, White');
writeln (' 2: 320x200, Green, Red, Brown');
writeln (' 3: 320x200, Cyan, Magenta, Lightgrey');
writeln (' 4: 640x200, one colour');
writeln (' 5: 640x400, four colour');
writeln (' 6: 640x400, one colour');
end;
{$ENDIF}
end; {case}
grmode := modehi;
repeat
write ('Enter Graphic Mode (',grmode,'): ');
readln (message);
if message = '' then
str (grmode,message);
val(message,num,code);
until ((code = 0) and (trunc(num) in [modelow..modehi]));
grmode := trunc(num);
end; {then}
setgraphmode(grmode);
CLOSEGRAPH;
if graphresult = 0 then; {clear the graphresult}
initgraph (grsys,grmode,BGIDIR);
message := grapherrormsg (graphresult);
driveron := message = 'No error';
restorecrtmode;
viewchanged := true;
end; { while }
ngraphchar := GetMaxX div 8;
GXmin := 0;
GXMax := GetMaxX ;
Gymin := 0;
GYMax := GetMaxY;
Ncolors := GetMaxColor;
if grsys = RESERVED then
setsys; {force display of menu}
end; { procedure SETSYS }
function CHECKEY: boolean;
{ Return TRUE if the 'A' key has been pressed, or FALSE otherwise }
var c: char;
begin
c := ' ';
if (keypressed) then begin
c := readkey;
if (upcase (c) = 'A') then
Checkey := TRUE
else
Checkey := FALSE;
end else
Checkey := FALSE;
end; { function CHECKEY }
{ GRAFSTAT and STOPSTAT control the plotting of "status dots" at the bottom
of the graphics screen. STOPSTAT clears the line away and also
reinitializes the local (static) variables.
}
var Statpos: integer; { next X-position to plot a status dot }
procedure STOPSTAT;
var c: char;
begin
Statpos := Gxmin+3;
gdraw (Gxmin+1, Gymax-1, Gxmax-1, Gymax-1, 0);
{ Clear out the console input buffer }
while (keypressed) do
c := readkey;
end; { procedure STOPSTAT }
function GRAFSTAT: boolean;
{ Every call to GRAFSTAT produces a new status dot, and also
checks the keyboard for a run abort. GRAFSTAT returns TRUE if the
user wishes to abort the run (by pressing the 'A' key), or FALSE otherwise.
}
begin
Statpos := Statpos + 1;
if (Statpos > Gxmax-3) then
stopstat;
gplot (Statpos, Gymax-1, 1);
Grafstat := checkey;
end; { procedure GRAFSTAT }
procedure SETGMODE;
{ Set up graphics mode and draw the window }
var
message: string;
temp : integer;
begin
setgraphmode(grmode);
temp := (graphresult);
message := grapherrormsg(temp);
if message <> 'No error' then begin
restorecrtmode;
writeln;
writeln ('SETGraphMODE: BGI error: ',message);
writeln ('Error number: ',temp);
writeln ('GrSys is: ',Grsys);
writeln ('GrMode is: ',Grmode);
writeln ('SurfModl Halted');
halt;
end
else begin
gdraw (Gxmin, Gymin, Gxmax, Gymin, 1);
gdraw (Gxmax, Gymin, Gxmax, Gymax, 1);
gdraw (Gxmax, Gymax, Gxmin, Gymax, 1);
gdraw (Gxmin, Gymax, Gxmin, Gymin, 1);
stopstat; { Initialize the graphics status line }
setcolor(1);
if ngraphchar < length (flpurpose) then
flpurpose := copy (flpurpose,1,ngraphchar);
outtextXY ((ngraphchar - length(flpurpose)) * 4,1 ,Flpurpose);
end; {else}
end; { procedure SETGMODE }
function savescrn (filename : string) : boolean;
var
imagefile : file;
bitmap : pointer;
success : boolean;
begin
success := true;
getmem (bitmap,imagesize(0,0,GetMaxX, GetMaxY));
if bitmap = nil then {error}
success := false
else begin
getimage (0,0,GetMaxX,GetMaxY,bitmap^);
putimage (0,0,bitmap^,NOTput);
if (graphresult = GrOK) AND (bitmap <> nil) then begin
{$I-}
assign (imagefile,filename);
if ioresult <> 0 then
success := false;
rewrite (imagefile,1);
if ioresult <> 0 then
success := false;
blockwrite (imagefile,grsys,sizeof(grsys));
if ioresult <> 0 then
success := false;
blockwrite (imagefile,grmode,sizeof(grmode));
if ioresult <> 0 then
success := false;
blockwrite (imagefile,bitmap^,imagesize(0,0,GetMaxX, GetMaxY));
if ioresult <> 0 then
success := false;
close (imagefile);
if ioresult <> 0 then
success := false;
{$I+}
end { Image successfuly read }
else { getimage not successful }
success := false;
putimage (0,0,bitmap^,NormalPut);
release (bitmap);
end; {memory available}
savescrn := success;
end; {savescrn}
function readscrn (filename : string; var grsys,grmode : integer;
var bitmap : pointer) : boolean;
var
imagefile : file;
success : boolean;
begin
success := true;
{$I-}
assign (imagefile,filename);
if ioresult <> 0 then begin
success := false;
writeln ('File "',filename,'" not found');
end;
reset (imagefile,1);
if ioresult <> 0 then begin
success := false;
writeln ('File "',filename,'" not found');
end;
blockread (imagefile,grsys,sizeof(grsys));
if ioresult <> 0 then begin
success := false;
writeln ('Could not read grsys');
end;
blockread (imagefile,grmode,sizeof(grmode));
if ioresult <> 0 then begin
success := false;
writeln ('Could not read grmode');
end;
{$I+}
if success then begin
getmem (bitmap,filesize(imagefile) - sizeof(grmode) - sizeof(grsys));
if bitmap = nil then begin
success := false;
writeln ('Could not allocate memory for bitmap');
end
else begin {memory successfully allocated}
{$I-}
blockread (imagefile,bitmap^,filesize(imagefile) - sizeof(grmode)
- sizeof(grsys));
if ioresult <> 0 then begin
success := false;
writeln ('Could not read image');
end;
{$I+}
end; {Memory allocated}
end; { Image successfuly read }
{$I-}
close (imagefile);
{$I+}
if ioresult <> 0 then
success := false;
readscrn := success;
end; {readscrn}
{************************************************************************}
function get_env
(env_var: String) { environment variable to look for }
: String; { Value of environment variable }
{ }
{ Description: }
{ Returns the value associated with the given environment variable }
{ }
{************************************************************************}
{ }
{ Revision History: }
{ "a" means Alpha version, Not Completed }
{ "b" means Beta Test Version, Completed but in testing }
{ "c" means Completed Version. This version is now frozen }
{ }
{************************************************************************}
var
i,j: integer;
result: String;
found: boolean;
table_address: integer;
begin { get_environment }
result := '';
i := 0;
table_address := memW[PrefixSeg:$002c];
if length (env_var) <> 0 then begin
for j := 1 to length(env_var) do begin {convert to uppercase}
if env_var[j] in ['a'..'z'] then begin
env_var[j] := chr(ord(env_var[j])-32);
end; {then}
end; {for}
repeat
result := '';
while (mem[table_address:i]) <> 0 do begin
result := result + chr(mem[table_address:i]);
i := i + 1;
end;
if pos (env_var,result) = 1 then begin
found := true;
result := copy (result,length(env_var) + 2,length(result));
end
else
found := false;
i := i + 1;
until found or (result = '');
end; { Then find value }
get_env := result;
end; {get_env}
{The following procedures link in the appropriate .OBJ files so the graphics }
{drivers are always memory resident. If you get an error message, then you }
{must copy the .BGI files into this directory, then run the BGI2OBJ batch }
{file. It uses the turbo pascal 4.0 utility BINOBJ. }
{$IFDEF LINKATT}
{$DEFINE LINKING}
procedure ATTDriver; external;
{$L ATT.OBJ }
{$ENDIF}
{$IFDEF LINKCGA}
{$DEFINE LINKING}
procedure CgaDriver; external;
{$L CGA.OBJ }
{$ENDIF}
{$IFDEF LINKEGAVGA}
{$DEFINE LINKING}
procedure EgaVgaDriver; external;
{$L EGAVGA.OBJ }
{$ENDIF}
{$IFDEF LINKHERC}
{$DEFINE LINKING}
procedure HercDriver; external;
{$L HERC.OBJ }
{$ENDIF}
{$IFDEF LINKPC3270}
{$DEFINE LINKING}
procedure PC3270Driver; external;
{$L PC3270.OBJ }
{$ENDIF}
{$IFDEF LINKING}
procedure Abort(Msg : string);
begin
Writeln(Msg, ': ', GraphErrorMsg(GraphResult));
Halt(1);
end;
{$ENDIF}
BEGIN
driveron := false;
DoRandom := false;
RandShade := 1.0 / 16.0;
Mono := true;
grsys := -1;
grmode := -1;
viewchanged := true;
{Get the directory the .BGI drivers are in}
BGIDIR := get_env('BGIDIR');
{$IFDEF LINKCGA}
if RegisterBGIdriver(@CGADriver) < 0 then
Abort('CGA');
{$ENDIF}
{$IFDEF LINKEGAVGA}
if RegisterBGIdriver(@EGAVGADriver) < 0 then
Abort('EGA/VGA');
{$ENDIF}
{$IFDEF LINKHERC}
if RegisterBGIdriver(@HercDriver) < 0 then
Abort('Herc');
{$ENDIF}
{$IFDEF LINKATT}
if RegisterBGIdriver(@ATTDriver) < 0 then
Abort('AT&T');
{$ENDIF}
{$IFDEF LINKPC2370}
if RegisterBGIdriver(@PC3270Driver) < 0 then
Abort('PC 3270');
{$ENDIF}
{vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv}
{If you get an error message, "Error 15: File not found (xxx.OBJ)" then you }
{must copy the .BGI files into this directory, then run the BGI2OBJ batch }
{file. It uses the turbo pascal 4.0 utility BINOBJ so it must be available }
{^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^}
END.